home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
LIBRARY
/
FUTILS
/
FSTACK.DOC
< prev
next >
Wrap
Text File
|
1989-02-19
|
7KB
|
227 lines
/\ RKCP /\
\/ RKCP \/
********************************************************************
************************ FSTACK by Rex Kerr ************************
************************ Copyright (C) 1989 ************************
********************************************************************
This is a Turbo Pascal unit written in assembly language that lets
you create stacks that can be used like the CPU's main stack. You
can have either byte or word stacks, and you can switch as often as
you like. You can only have one active byte or words stack at one
time, though.
There are 7 routines for word stacks, and seven more for byte stacks.
***
InitWStack(var buf; len : word);
This initializes the word stack. Len is the length of buf. If you
are passing a pointer to something, make sure you pass the something
instead of the pointer;
var st : ^string;
begin
new(st);
initwstack(st^,sizeof(st^)); { Right. }
initwstack(st,sizeof(st)); { Now your buffer is the pointer!
You only have 4 bytes! }
initwstack(st,sizeof(st^)); { This is dangerous! If you do
too much pushing, you'll run
past the 4 byte pointer ... }
initwstack(st^,sizeof(st)); { This is horrible! You have 256
bytes available, but have said
you only have 4 }
dispose(st);
end.
***
InitBStack(var buf; len : word);
This is exactly the same as InitWStack, except it initializes the
byte stack.
***
ClearWStack;
This just clears the word stack.
***
ClearBStack;
This clears the byte stack.
***
WStackEmpty : boolean;
This returns true if the word stack is empty.
***
BStackEmpty : boolean;
This returns true if the byte stack is empty.
***
PushW(w : word);
This pushes one word onto the word stack (if it isn't full).
***
PushB(b : byte);
This pushes one byte onto the byte stack (if it isn't full).
***
PopW : word;
This pops one word from the word stack. It is a function for
flexibility and speed.
***
PopB : byte;
This pops one byte from the byte stack.
***
WStackSize : word;
This returns the current number of entries in the word stack. To
find the maximum word size do:
Max_Size := sizeof(buf) shr 1;
And to find the number of free spaces (assuming you have found
Max_Size) you do:
free_spaces := Max_Size - WStackSize;
***
BStackSize : word;
BStackSize returns the number of entries in the byte stack.
Max_Size for the byte stack is the same thing as sizeof(buf).
***
SetWStack(size : word);
You use this for swapping stacks. Like this:
var bufa,bufb : array[1..100] of byte;
sizea : word
begin
initwstack(bufa,sizeof(bufa)); { Initialize the stack }
( . . . ) { Do some stuff to it }
sizea := wstacksize; { Get the size of the stack }
initwstack(bufb,sizeof(bufb)); { Re-initialize stack #2 }
( . . . ) { Do whatever with stack #2 }
initwstack(bufa,sizeof(bufa)); { Back to stack #1, but it's
empty }
setwstack(sizea); { Now we're back to the first
stack the way it was }
end.
Please note that only pushes actually change the values in the
stack. The others just set different hidden variables or read
from the stack. SetWStack just sets the length of the stack to
what size you specify; it in no way changes the contents of the
stack. ClearWStack just calls SetWStack(0).
***
SetBStack(size : word);
This does for the byte stack what SetWStack does for the word stack.
***
One useful place for this is in a non-recursive form of QuickSort.
For short stacks, FSTACK is much better than a linked list stack.
Here are the reasons why:
1) It is much faster (3 or 4 times, I think)
2) It has no overhead per item
3) You can access the stack as an array
You also can have just the amount of space you want like this:
program Get_Just_Enough;
uses fstack;
type stackarry : array[1..100] of byte;
var b : ^stackarry;
len : word;
begin
len := 14; { Or however much you need }
getmem(b,len); { Get the memory }
initstack(b^,sizeof(b^)); { Initialize the stack }
( . . . ) { Use the stack }
freemem(b,len); { Free the memory used }
end.
It isn't a good idea to reallocate b while you are using the stack,
in case the place where b is stored is moved. If it is moved,
you can fix that with FSWAP. Like this:
uses fswap,fstack;
type stackarry := array[1..100] of word;
{ If range checking is off, the 1..100 may be any size. If it's on,
it must be at least as large as the largest getmem (to avoid a
range check error) }
var len,size : word; { len is to store the getmem value,
size is to store wstacksize }
b,temptr : ^stackarry; { You'll need the extra pointer }
begin
len := 14; { Set getmem length }
getmem(b,len); { Get the memory }
initwstack(b^,len); { Initialize the stack }
( . . . ) { Use the stack & find it is too small }
temptr := b; { Save the address of the buffer }
freemem(b,len); { Free the buffer's memory }
len := 28; { Set the new length }
getmem(b,len); { Get the memory }
size := wstacksize; { Get the stack size }
if temptr <> b then { If temptr <> b, the b has been moved }
begin
qswapv(temptr,b,size); { Move the stack values to the
end; new location }
initwstack(b^,len); { Re-initialize the stack to the new
maximum length (and maybe location) }
setwstack(size); { Set the stack to use the old pushed
values }
( . . . ) { Do whatever you want }
freemem(b,len); { Free the allocated memory }
end. { We're done. }
All of the byte stack things work just like the word stack things,
except you push and pop bytes. You will probably have to use
value typecasting (for things like characters and integers).
And also you'll have to split things like longints up. When you
are doing that, remember that if you push the high part first and
then the low part, you should pop the low part and then the high
part to get it back the same way.
I've thought of a zillion things to use this for, and I'm hoping
it will be just as useful to everyone else.
If I seem to have left something out or if things are unclear please
let me know via CompuServe on either EasyPlex or BPROGAs TP5 message
section.
Rex Kerr 71550,3147
/\ RKCP /\
\/ RKCP \/